package com.smart.redis.list;

import java.util.List;

import com.smart.redis.client.RedisClient;

import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.Jedis;

/**
 * 
 * redis 中list的数据结构模型是
 * map<k,List<?>> 
 * 每个 list 可以存储40多亿个键值对（2的32次方减1）
* @ClassName: Redis2List 
* @Description: TODO redis list列表操作
* @Company:e-smart.top
* @author Thinkpad 
* @version 1.0 2018年8月29日 下午4:08:11
 */
public class Redis2List {
	
	/**
	 * 
	* 由于没有等待时间参数，此法在没有获取到列表的情况下会一直阻塞连接
	*
	* @Title: blpop 
	* @Description: TODO 弹出并获取列表的第一个元素
	* @param @param keys
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	@Deprecated
	public static List<String> blpop(String... keys){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> blpop = jedis.blpop(keys);
			return blpop;
		} catch (Exception e) {
			// TODO: blpop 
			System.err.println("blpop : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}

	/**
	 * 
	* 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为
	*
	* @Title: blpop 
	* @Description: TODO  弹出并获取列表的第一个元素
	* @param @param timeout 阻塞时间-秒
	* @param @param key
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String> blpop(int timeout,String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> blpop = jedis.blpop(timeout, key);
			return blpop;
		} catch (Exception e) {
			// TODO: blpop 
			System.err.println("blpop : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	
	/**
	 * 
	* 当给定列表内没有任何元素可供弹出的时候，连接将被 BLPOP 命令阻塞，直到等待超时或发现可弹出元素为止
	* 当给定多个 key 参数时，按参数 key 的先后顺序依次检查各个列表，弹出第一个非空列表的头元素
	* 不太好理解什么时候阻塞什么时候不阻塞
	* 
	* @Title: blpop 
	* @Description: TODO  弹出并获取列表的第一个元素
	* @param @param timeout
	* @param @param keys
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String> blpop(int timeout,String... keys){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> blpop = jedis.blpop(timeout, keys);
			return blpop;
		} catch (Exception e) {
			// TODO: blpop 
			System.err.println("blpop : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 由于没有等待时间参数，此法在没有获取到列表的情况下会一直阻塞连接
	* 
	* @Title: brpop 
	* @Description: TODO  弹出并获取列表的最后一个元素
	* @param @param keys
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	@Deprecated
	public static List<String> brpop(String... keys){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> brpop = jedis.brpop(keys);
			return brpop;
		} catch (Exception e) {
			// TODO: brpop 
			System.err.println("brpop : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: brpop 
	* @Description: TODO 弹出并获取列表的最后一个元素
	* @param @param timeout
	* @param @param key
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String> brpop(int timeout,String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> brpop = jedis.brpop(timeout, key);
			return brpop;
		} catch (Exception e) {
			// TODO: brpop 
			System.err.println("brpop : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 当给定列表内没有任何元素可供弹出的时候，连接将被 BRPOP 命令阻塞，直到等待超时或发现可弹出元素为止
	* 
	* @Title: brpop 
	* @Description: TODO 弹出并获取列表的最后一个元素
	* @param @param timeout
	* @param @param keys
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String> brpop(int timeout,String... keys){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> brpop = jedis.brpop(timeout, keys);
			return brpop;
		} catch (Exception e) {
			// TODO: brpop 
			System.err.println("brpop : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	
	/**
	 * 
	*
	* @Title: lindex 
	* @Description: TODO 获取列表中指定位置的字符串数据 
	* @param @param key
	* @param @param index 索引（从0开始）
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String lindex(String key,long index){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String lindex = jedis.lindex(key, index);
			return lindex;
		} catch (Exception e) {
			// TODO: lindex 
			System.err.println("lindex : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 当 pivot 不存在于列表 key 时，不执行任何操作。
	* 当 key 不存在时， key 被视为空列表，不执行任何操作。
	* 如果 key 不是列表类型，返回一个错误。
	* 返回值：
	* 	如果命令执行成功，返回插入操作完成之后，列表的长度。
	* 	如果没有找到 pivot ，返回 -1 。
	* 	如果 key 不存在或为空列表，返回 0 。
	* 
	* @Title: linsertBefore 
	* @Description: TODO 在key对应的列表中的元素pivot之前插入value元素
	* @param @param key 键
	* @param @param pivot 要插入的位置元素
	* @param @param value 要插入的元素
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long linsertBefore(String key,String pivot,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long linsert = jedis.linsert(key, LIST_POSITION.BEFORE, pivot, value);
			return linsert;
		} catch (Exception e) {
			// TODO: linsert before
			System.err.println("linsert before: "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 当 pivot 不存在于列表 key 时，不执行任何操作。
	* 当 key 不存在时， key 被视为空列表，不执行任何操作。
	* 如果 key 不是列表类型，返回一个错误。
	* 返回值：
	* 	如果命令执行成功，返回插入操作完成之后，列表的长度。
	* 	如果没有找到 pivot ，返回 -1 。
	* 	如果 key 不存在或为空列表，返回 0 。
	* 
	* @Title: linsertAfter 
	* @Description: TODO 在key对应的列表中的元素pivot之后插入value元素 
	* @param @param key 键
	* @param @param pivot 要插入的位置元素
	* @param @param value 要插入的元素
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long linsertAfter(String key,String pivot,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long linsert = jedis.linsert(key, LIST_POSITION.AFTER, pivot, value);
			return linsert;
		} catch (Exception e) {
			// TODO: linsert after
			System.err.println("linsert after: "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: llen 
	* @Description: TODO 获取key对应列表的长度 
	* @param @param key
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long llen(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long llen = jedis.llen(key);
			return llen;
		} catch (Exception e) {
			// TODO: llen
			System.err.println("llen : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: lpop 
	* @Description: TODO 移除并返回key对应列表的第一个元素 
	* @param @param key
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String lpop(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String lpop = jedis.lpop(key);
			return lpop;
		} catch (Exception e) {
			// TODO: lpop
			System.err.println("lpop : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	
	/**
	 * 
	* 如果有多个 value 值，那么各个 value 值按从左到右的顺序依次插入到表头
	* 如果 key 不存在，一个空列表会被创建并执行 LPUSH 操作。
	* 当 key 存在但不是列表类型时，返回一个错误。
	*
	* @Title: lpush 
	* @Description: TODO 将一个或多个值 value 插入到列表 key 的表头 
	* @param @param key
	* @param @param values
	* @param @return    设定文件 
	* @return Long    返回列表长度
	* @throws
	 */
	public static Long lpush(String key,String... values ){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long lpush = jedis.lpush(key, values);
			return lpush;
		} catch (Exception e) {
			// TODO: lpush
			System.err.println("lpush : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: lpushx 
	* @Description: TODO 将值 value 插入到列表 key 的表头，当且仅当 key 存在并且关联的数据是一个列表 
	* @param @param key
	* @param @param values
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long lpushx(String key,String... values ){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long lpushx = jedis.lpushx(key, values);
			return lpushx;
		} catch (Exception e) {
			// TODO: lpushx
			System.err.println("lpushx : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 start 下标比列表的最大下标 END ( LLEN list 减去 1 )还要大，那么 LRANGE 返回一个空列表
	* 如果 end 下标比 列表最后一个元素END 下标还要大，Redis将 end 的值设置为 END
	* @Title: lrange 
	* @Description: TODO 获取key关联列表中的指定范围内的数据集合
	* @param @param key 键
	* @param @param start 开始索引（包含）-索引从0开始
	* @param @param end 结束索引（包含）
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String> lrange(String key,long start,long end){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> lrange = jedis.lrange(key, start, end);
			return lrange;
		} catch (Exception e) {
			// TODO: lrange
			System.err.println("lrange : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* count 的值可以是以下几种：
	* 	count > 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count 。
	* 	count < 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值。
	* 	count = 0 : 移除表中所有与 value 相等的值。
	* 因为不存在的 key 被视作空表(empty list)，所以当 key 不存在时， LREM 命令总是返回 0 。
	* 
	* @Title: lrem 
	* @Description: TODO 移除列表中与value相等的列表中的值 
	* @param @param key
	* @param @param count
	* @param @param value
	* @param @return    设定文件 
	* @return Long    被移除元素的数量 
	* @throws
	 */
	public static Long lrem(String key,long count,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long lrem = jedis.lrem(key, count, value);
			return lrem;
		} catch (Exception e) {
			// TODO: lrem
			System.err.println("lrem : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: lset 
	* @Description: TODO  将key关联的列表中index位置处的值设置为value
	* @param @param key 键
	* @param @param index 索引-从0开始
	* @param @param value 要设置的值
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static Boolean lset(String key,long index,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String lset = jedis.lset(key, index, value);
			System.out.println("lset : "+lset);
			return true;
		} catch (Exception e) {
			// TODO: lset
			System.err.println("lset : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 当 key 不是列表类型时，返回一个错误。
	* 如果 start 下标比列表的最大下标 END ( LLEN list 减去 1 )还要大，或者 start > stop ， LTRIM 返回一个空列表(因为 LTRIM 已经将整个列表清空)
	* 如果 end 下标比 END 下标还要大，Redis将 end 的值设置为 END
	* @Title: ltrim 
	* @Description: TODO 保留key关联的列表中指定范围的数据，范围之外的数据会被删除 
	* @param @param key
	* @param @param start 开始索引（包含）-从0开始
	* @param @param end 结束索引（包含）
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static Boolean ltrim(String key,long start,long end){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String ltrim = jedis.ltrim(key, start, end);
			System.out.println("ltrim : "+ltrim);
			return true;
		} catch (Exception e) {
			// TODO: ltrim
			System.err.println("ltrim : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: rpop 
	* @Description: TODO 移除并返回key对应列表的最后一个元素 
	* @param @param key
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String rpop(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String rpop = jedis.rpop(key);
			return rpop;
		} catch (Exception e) {
			// TODO: rpop
			System.err.println("rpop : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 srckey 不存在，值 nil 被返回，并且不执行其他动作。
	* 如果 两个列表相同，则列表中的表尾元素被移动到表头，并返回该元素，可以把这种特殊情况视作列表的旋转
	* 
	* @Title: rpoplpush 
	* @Description: TODO 将一个列表中的最后一个元素移出，并插入到另一个列表中 ，最后返回移出的这个元素
	* @param @param srckey 要移出元素的列表键
	* @param @param dstkey 要插入元素的列表键
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String rpoplpush(String srckey,String dstkey){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String rpoplpush = jedis.rpoplpush(srckey, dstkey);
			return rpoplpush;
		} catch (Exception e) {
			// TODO: rpoplpush
			System.err.println("rpoplpush : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 当srckey关联列表为空时该方法会阻塞连接，阻塞时间过后，释放连接，
	* 或者在阻塞时间内，另一个客户端对srckey列表添加了数据
	* 当阻塞时间为0时，阻塞时间为无限长
	*
	* @Title: brpoplpush 
	* @Description: TODO rpoplpush的阻塞版本 
	* @param @param srckey 要移出元素的列表键
	* @param @param dstkey 要插入元素的列表键
	* @param @param timeout 阻塞时间 单位秒/s
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String brpoplpush(String srckey,String dstkey,int timeout){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String brpoplpush = jedis.brpoplpush(srckey, dstkey,timeout);
			return brpoplpush;
		} catch (Exception e) {
			// TODO: brpoplpush
			System.err.println("brpoplpush : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 key 不存在，一个空列表会被创建并执行 RPUSH 操作
	* 当 key 存在但不是列表类型时，报错。
	*
	* @Title: rpush 
	* @Description: TODO 将一个或多个值 value 插入到列表 key 的表尾(最右边) 
	* @param @param key
	* @param @param values
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long rpush(String key,String... values){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long rpush = jedis.rpush(key, values);
			return rpush;
		} catch (Exception e) {
			// TODO: rpush
			System.err.println("rpush : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 当 key 不存在时， RPUSHX 命令什么也不做
	* 
	* @Title: rpushx 
	* @Description: TODO 将值 value 插入到列表 key 的表尾，当且仅当 key 存在并且是一个列表
	* @param @param key
	* @param @param values
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long rpushx(String key,String... values){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long rpush = jedis.rpushx(key, values);
			return rpush;
		} catch (Exception e) {
			// TODO: rpush
			System.err.println("rpush : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
}
